using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Xml;
using Urs.Data.Domain.Common;
using Urs.Data.Domain.Orders;

namespace Urs.Data.Domain.Users
{
    public static class UserExtentions
    {
        #region User role

        /// <summary>
        /// Gets a value indicating whether user is in a certain user role
        /// </summary>
        /// <param name="user">User</param>
        /// <param name="userRoleSystemName">role system name</param>
        /// <param name="onlyActiveUserRoles">A value indicating whether we should look only in active user roles</param>
        /// <returns>Result</returns>
        public static bool IsInUserRole(this User user,
            string userRoleSystemName, bool onlyActiveUserRoles = true)
        {
            if (user == null)
                throw new ArgumentNullException("user");

            if (String.IsNullOrEmpty(userRoleSystemName))
                throw new ArgumentNullException(nameof(userRoleSystemName));

            var result = user.UserRoles
                .Where(cr => !onlyActiveUserRoles || cr.Active)
                .Where(cr => cr.SystemName == userRoleSystemName)
                .FirstOrDefault() != null;
            return result;
        }

        /// <summary>
        /// Gets a value indicating whether user is administrator
        /// </summary>
        /// <param name="user">User</param>
        /// <param name="onlyActiveUserRoles">A value indicating whether we should look only in active user roles</param>
        /// <returns>Result</returns>
        public static bool IsAdmin(this User user, bool onlyActiveUserRoles = true)
        {
            return IsInUserRole(user, SystemRoleNames.Administrators, onlyActiveUserRoles);
        }

        public static bool IsRegistered(this User user, bool onlyActiveUserRoles = true)
        {
            return IsInUserRole(user, SystemRoleNames.Registered, onlyActiveUserRoles);
        }
        /// <summary>
        /// Gets a value indicating whether user is guest
        /// </summary>
        /// <param name="user">User</param>
        /// <param name="onlyActiveUserRoles">A value indicating whether we should look only in active user roles</param>
        /// <returns>Result</returns>
        public static bool IsGuest(this User user, bool onlyActiveUserRoles = true)
        {
            return IsInUserRole(user, SystemRoleNames.Guests, onlyActiveUserRoles);
        }

        #endregion

        #region Addresses

        public static void RemoveAddress(this User user, Address address)
        {
            if (user.Addresses.Contains(address))
            {
                if (user.ShippingAddress == address) user.ShippingAddress = null;

                user.Addresses.Remove(address);
            }
        }

        #endregion

        #region Reward points

        public static void AddRewardPointsHistoryEntry(this User user,
            int points, string message = "",
            Order usedWithOrder = null, decimal usedAmount = 0M)
        {
            int newPointsBalance = user.GetRewardPointsBalance() + points;

            var rewardPointsHistory = new PointsHistory()
            {
                User = user,
                UsedWithOrder = usedWithOrder,
                Points = points,
                PointsBalance = newPointsBalance,
                UsedAmount = usedAmount,
                Message = message,
                CreateTime = DateTime.Now
            };

            user.PointsHistory.Add(rewardPointsHistory);
        }

        /// <summary>
        /// Gets reward points balance
        /// </summary>
        public static int GetRewardPointsBalance(this User user)
        {
            int result = 0;
            if (user.PointsHistory.Count > 0)
                result = user.PointsHistory
                    .OrderByDescending(rph => rph.CreateTime)
                    .ThenByDescending(rph => rph.Id)
                    .FirstOrDefault()
                    .PointsBalance;
            return result;
        }

        #endregion

    }
}
